package com.zbs.simbot.factory.abstracts;

import com.zbs.simbot.annotations.Func;
import com.zbs.simbot.config.SimBotConfig;
import com.zbs.simbot.constants.BaseConstants;
import com.zbs.simbot.enums.MsgType;
import com.zbs.simbot.enums.PermissionEnum;
import com.zbs.simbot.enums.QQListType;
import com.zbs.simbot.events.BaseMsgEvent;
import com.zbs.simbot.factory.BasePlugin;
import com.zbs.simbot.factory.dto.PluginInfo;
import love.forte.simbot.definition.Member;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

public abstract class AbstractsBasePlugin implements BasePlugin {
    @Override
    public Integer getOrder() {
        return -1;
    }

    @Override
    public void defaultRun(BaseMsgEvent event, BasePlugin plugin) {
        PluginInfo info = this.getInfo();
        Long baseId;
        if (event.getMsgType().equals(MsgType.GROUP)) {
            baseId = Long.parseLong(event.getGroup().getId().toString());
        } else {
            baseId = event.getUserId();
        }
        List<Long> whitelist = info.getWhitelist();
        List<Long> blacklist = info.getBlacklist();
        if (info.getListType().equals(QQListType.NONE)) {
            doRunFun(event, plugin);
        }
        if (info.getListType().equals(QQListType.WHITE) && whitelist.contains(baseId)) {
            doRunFun(event, plugin);
        }
        if (info.getListType().equals(QQListType.BLACK) && !blacklist.contains(baseId)) {
            doRunFun(event, plugin);
        }
    }

    /**
     * 开始执行插件
     * @param event 事件
     * @param plugin 插件
     */
    private void doRunFun(BaseMsgEvent event, BasePlugin plugin) {
        if (StringUtils.hasLength(event.getFullMsg())) {
            Class<? extends BasePlugin> aClass = plugin.getClass();
            Method[] methods = aClass.getMethods();
            String msg = event.getMsg();
            // 获取插件内的方法
            Arrays.stream(methods).forEach(method -> {
                // 获取方法上的注解
                Func func = method.getAnnotation(Func.class);
                if (func != null) {
                    // 如果 func 设置了@机器人触发  消息并且是群消息，直接放行，不需要匹配正则
                    if (func.atBot() && event.isAtBot() && event.getMsgType().equals(MsgType.GROUP)) {
                        invoke(func,method,aClass,event);
                        return;
                    }
                    // 是否忽略正则
                    if (func.ignoreReg()) {
                        // 忽略正则，直接执行方法，func 选择接收的消息类型 如果事件消息类型满足接收消息类型，直接放行，ALL 是接收所有的消息
                        if (func.msgType().equals(MsgType.ALL) || BaseConstants.isSendMsg(func.msgType(),event.getMsgType())) {
                            invoke(func, method,aClass,event);
                        }
                        return;
                    }
                    // 方法的正则校验
                    if (StringUtils.hasLength(func.reg())) {
                        if (Pattern.matches(func.reg(), msg)) {
                            // 满足正则 且 同时满足接收的消息类型，直接放行
                            if (func.msgType().equals(MsgType.ALL) || BaseConstants.isSendMsg(func.msgType(),event.getMsgType())) {
                                invoke(func, method,aClass,event);
                            }
                        }
                    }
                }
            });
        }
    }

    /**
     * 判断非群消息，并且禁用私聊功能
     * 如果禁用私聊功能，非主人QQ号，以及 方法上 disablePrivateCanPass 允许私聊 直接禁止私聊，不在执行下面的功能
     * @param event 事件
     * @param func 注解
     * @return boolean
     */
    protected boolean accept(BaseMsgEvent event, Func func) {
        if (!event.getMsgType().equals(MsgType.GROUP)) {
            if (SimBotConfig.disablePrivate && !SimBotConfig.masterQq.contains(event.getUserId()) && !func.disablePrivateCanPass()) {
                event.send(SimBotConfig.disableMsg);
                return true;
            }
        }
        return false;
    }

    /**
     * 执行的方法
     * @param func 注解
     * @param method 方法
     * @param aClass 插件
     * @param event 事件
     */
    protected void invoke(Func func, Method method, Class<? extends BasePlugin> aClass, BaseMsgEvent event) {
        try {
            // 判断私聊功能 是否禁用
            boolean accept = this.accept(event, func);
            if (accept) {
                return;
            }
            // 判断方法权限
            if (func.permission() !=null && func.permission().equals(PermissionEnum.MASTER) && !event.isAuthorMasterQQ()) {
                event.send("对不起，你不是主人，只有主人才可以用哦！");
                return;
            }
            // 判断方法群权限
            if (event.getMsgType().equals(MsgType.GROUP)) {
                if (func.permission() !=null && func.permission().equals(PermissionEnum.OWNER)) {
                    Member user = (Member) event.getUser();
                    boolean owner = user.isOwner();
                    if (!owner) {
                        event.send("对不起，你不是群主，不可以使用哦！");
                        return;
                    }
                }
                if (func.permission() !=null && func.permission().equals(PermissionEnum.ADMIN)) {
                    Member user = (Member) event.getUser();
                    boolean admin = user.isAdmin();
                    if (!admin) {
                        event.send("对不起，你不是群管理，不可以使用哦！");
                        return;
                    }
                }
            }

            // 方法上不需要 BaseMsgEvent ，可以不传参
            if (method.getParameters().length == 0) {
                method.invoke(aClass.getDeclaredConstructor().newInstance());
            }
            // 方法上 只有1个参数，且接收参数必须 BaseMsgEvent
            if (method.getParameters().length == 1) {
                method.invoke(aClass.getDeclaredConstructor().newInstance(), event);
            }
        } catch (IllegalAccessException | InvocationTargetException | InstantiationException |
                 NoSuchMethodException ignored) {
        }
    }
}
